#ifndef _MODULES_H_CSEAPI_
#define _MODULES_H_CSEAPI_

class CSE_IMPEXP_IN TCseRegister
{
public:
    TBool exist(const TCharArray& key);
    TCseObj get(const TCharArray& key);
    const TCseObj& set(const TCharArray& key, const TCseObj& value);
    void remove(const TCharArray& key);

    TCseObj hold(const TCseObj& value);
};

extern CSE_IMPEXP_IN TCseRegister *CseRegister;

class CSE_IMPEXP_IN TCseModule: public TCseObj
{
public:
    TCseModule(const TCharArray& sModule, TBool OnlyTopLevel=false);
    TCseModule(const TCseObj& module);

    static TCharArray searchFile(const TCharArray& sModule, const TCharArray& RefFile=CseEmptyStr, TBool SysInc=false);
    static TCseObj getModule(const TCharArray& sModule, TBool OnlyTopLevel=false);
    static void setModule(const TCharArray& sModule, const TCseObj& mod);
    static void *CFuncAddr(const TCseObj& vFunc);

    static TCseModule create(const TCharArray& sModule, TBool regist=true);
    static TCseModule loadCsd(const TCharArray& sModule, const TCharArray& RefFile=CseEmptyStr);
    static void unloadAll(TBool safeExit=false);

    TBool useModule(const TCseModule& module) const;

    void clear() const;
    const TCseObj& attrSet(const TCharArray& attr, const TCseObj& value) const;
    TCseObj attrGet(const TCharArray& attr) const;

    void addSymList(const TCharArray& name, TInt iFlag, TBool ErrWhenDup=true) const;
    int addSymAddr(void *addr) const;
    int addExitFunc(void *func) const; // exit function should be "void (*)()"
    int addModuleVar(const TCseObj& var) const;
    TBool addSubModule(const TCharArray& name, const TCseObj& SubModule) const;
};

extern CSE_IMPEXP_IN void CseModules_init();
extern CSE_IMPEXP_IN void CseModules_SetArg(int argc, TXchar **argv);
extern CSE_IMPEXP_IN void CseModules_SetArgA(int argc, TChar **argv);
extern CSE_IMPEXP_IN void CseModules_SetArgW(int argc, TWchar **argv);
extern CSE_IMPEXP_IN void CseModules_exit();

#define MEMBER_OFF(UdtType,attr)      (&(((UdtType *)0)->attr))
#define MEMBER_OFF2(UdtType,m1,m2)    ((void*)((char*)&(((UdtType *)0)->m2) - (char*)&(((UdtType *)0)->m1)))
#define METHOD_ADDR(UdtType,method)   Cse_FuncAddr(NULL,&UdtType::method)
#define FUNC_ADDR(addr)               Cse_FuncAddr(NULL,addr)

extern CSE_IMPEXP_IN void *Cse_FuncAddr(char *fmt,...);

extern CSE_IMPEXP_IN const TXchar *Cse_GetHost();
extern CSE_IMPEXP_IN void Cse_SetHost(const TXchar *name);
extern CSE_IMPEXP_IN TCseObj Cse_EvalScript(const TXchar *script);

#endif
